package optimizers.tools;

import java.util.ArrayList;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;

import optimizers.commons.GAConstants;
import optimizers.commons.GAIndiv;

import fitness.FitnessResult;
import parallelism.SystemFitnessEvaluationTask;
import parallelism.SystemFitnessResult;
import fitness.BistableResult;
import fitness.Fitness;

public class Pruner {

	public static GAIndiv prune(CompletionService<Object> cservice,GAIndiv indiv,Fitness myFitnessEval) {
		if (indiv.marks == null)
			indiv.marks = new ArrayList<String>();
		GAIndiv result = indiv.clone();
		FitnessResult fitres = myFitnessEval.evaluateFitness(result);
			result.setFitness(fitres);
			
		int taskCount = 0;
		for (int i = 0; i < indiv.getNoSimpleSequence(); i++) {
			for (int j = 0; j < indiv.getNoSimpleSequence(); j++) {
				if (result.getTemplate()[0][i][j]) {
					GAIndiv test = result.deleteActivation(i, j);
					cservice.submit(new SystemFitnessEvaluationTask(10000
							+ i * 1000 + j * 100 + 0 + 0, test, myFitnessEval));
					taskCount++;
				}
			}
		}

		for (int i = 1; i < indiv.getNoSimpleSequence(); i++) {
			for (int j = 0; j < indiv.getNoSimpleSequence(); j++) {
				if (result.getSequence()[i][j]) {
					GAIndiv test = result.deleteInhibition(i, j);
					cservice.submit(new SystemFitnessEvaluationTask(10000
							+ i * 1000 + j * 100 + 0 + 1, test, myFitnessEval));
					taskCount++;
				}
			}
		}

		for (int i = 0; i < indiv.getNoSimpleSequence() + 1; i++) {
			for (int j = 0; j < indiv.getNoSimpleSequence(); j++) {
				for (int k = 0; k < indiv.getNoSimpleSequence(); k++) {
					if (result.getTemplate()[i][j][k]) {
						GAIndiv test = result.deleteInhibitionLead(i, j, k);
						cservice.submit(new SystemFitnessEvaluationTask(
								10000 + i * 1000 + j * 100 + k * 10 + 2, test, myFitnessEval));
						taskCount++;
					}
				}
			}
		}

		for (int ii = 0; ii < taskCount; ii++) {
			try {
				SystemFitnessResult result1 = (SystemFitnessResult) cservice
						.take().get();
				FitnessResult score = result1.result;
				int index = result1.index;
				String index1 = String.valueOf(index);
				System.out.println(index1);
				int i = Integer.parseInt(index1.substring(1, 2));
				int j = Integer.parseInt(index1.substring(2, 3));
				int k = Integer.parseInt(index1.substring(3, 4));
				int type = Integer.parseInt(index1.substring(4, 5));
				switch (type) {
				case 0:
					System.out.println("Delete activation " + i + "," + j
							+ ", score: " + score.finalResult()
							+ " original: "
							+ result.getFitness().finalResult());
					if (score.finalResult() >= result.getFitness()
							.finalResult()) {
						result = result.deleteActivation(i, j);
						System.out.println("Deleted");
					} else if (score.finalResult() >= result.getFitness()
							.finalResult()
							* GAConstants.pruningThreshold) {
						result.marks.add((i + 1) + "->" + (j + 1));
						System.out
								.println("Marked " + (i + 1) + "->" + (j + 1));
					}
					break;
				case 1:
					System.out.println("Delete inhibition " + (i - 1) + "," + j
							+ ", score: " + score.finalResult()
							+ " original: "
							+ result.getFitness().finalResult());
					if (score.finalResult() >= result.getFitness()
							.finalResult()) {
						result = result.deleteInhibition(i, j);
						System.out.println("Deleted");
					} else if (score.finalResult() >= result.getFitness()
							.finalResult()
							* GAConstants.pruningThreshold) {
						result.marks.add("Inh" + i + "_" + (j + 1));
						System.out.println("Marked " + "Inh" + i + "_"
								+ (j + 1));
					}
					break;
				case 2:
					System.out.println("Delete inhibition lead " + i + "->Inh"
							+ j + "_" + k + ", score: "
							+ score.finalResult() + " original: "
							+ result.getFitness().finalResult());
					if (score.finalResult() >= result.getFitness()
							.finalResult()) {
						result = result.deleteInhibitionLead(i, j, k);
						System.out.println("Deleted");
					} else if (score.finalResult() >= result.getFitness()
							.finalResult()
							* GAConstants.pruningThreshold) {
						result.marks.add((i) + "->Inh" + (j + 1) + "_"
								+ (k + 1));
						System.out.println("Marked " + (i) + "->Inh" + (j + 1)
								+ "_" + (k + 1));
					}
					break;
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return result;
	}
}
